#include "bsp_i2c.h"

void i2c_init( I2C_Type * I2Cx){

    /*先关闭I2C*/
    I2Cx->I2CR &= ~(1<<7);
    
    /*设置通信频率；设置分频为640分频，通信频率为103.125kbit/s*/
    I2Cx->IFDR = 0x38;

    /*打开I2C*/
    I2Cx->I2CR |= 1<<7;
}

unsigned char i2c_master_start( I2C_Type * I2Cx, unsigned char addr, enum i2c_direction direction){

    /*判断I2C是否忙*/
    if( ((I2Cx->I2SR >> 5) & 0x01) == 1)
        return 1;

    /*设置主从模式，0表示从机，为1表示主机*/
    I2Cx->I2CR |= (1<<5) | (1<<4);

    /*打包数据*/
    I2Cx->I2DR =  (addr << 1) | direction;
    return 0;

}

unsigned char i2c_master_stop( I2C_Type * I2Cx){

    unsigned short timeout = 0xffff;

    /*清0寄存器I2CR的bit5:bit3*/
    I2Cx->I2CR &= ~((1<<5) | (1<<4) | (1<<3));

    /*判断I2C是否忙*/
    while( ((I2Cx->I2SR >> 5) & 0x01) == 1){
        timeout--;
        if(timeout == 0){
            return I2C_STATUS_TIMEOUT;
        }
    }
    return I2C_STATUS_OK;
}

unsigned char i2c_master_repeated_start( I2C_Type * I2Cx, unsigned char addr, enum i2c_direction direction){

    /*判断I2C是否忙*/
    /* I2C忙并且工作在从模式,跳出 */
	if(I2Cx->I2SR & (1 << 5) && (((I2Cx->I2CR) & (1 << 5)) == 0))		
		return 1;

    /*设置主从模式，0表示从机，为1表示主机*/
    I2Cx->I2CR |= (1<<5) | (1<<4) | (1<<2);

    /*打包数据*/
    I2Cx->I2DR =  (addr << 1) | direction;
    return 0;

}

/*错误检查和清除*/
unsigned char i2c_check_and_clear_error( I2C_Type * I2Cx , unsigned int status){
    
    /*检查是否为仲裁丢失错误*/
    if(status & (1<<4)){
        I2Cx->I2SR &= ~(1<<4);
        I2Cx->I2CR &= ~(1<<7);
        I2Cx->I2CR |= (1<<7);
        return I2C_STATUS_ARBITRATIONLOST;
    }
    else if (status & (1<<0)){
        return I2C_STATUS_NAK;
    }
    return I2C_STATUS_OK;

}

void i2c_master_write(I2C_Type * I2Cx , const unsigned char * buf , unsigned int size){
    
    /*等待上一次传输完成*/
    while( !( I2Cx->I2SR & (1<<7) ) );

    /*清除中断标志位*/
    I2Cx->I2SR &= ~(1<<1);

    /*设置发送模式*/
    I2Cx->I2CR |= 1<<4;

    while(size--){
        I2Cx->I2DR = *buf++;
        while ( !( I2Cx->I2SR & ( 1<<1 ) ) );/*等待发送完成*/
        I2Cx->I2SR &= ~(1<<1);

        /*检查ACK*/
        if(i2c_check_and_clear_error(I2Cx , I2Cx->I2SR))
            break;
    }

    I2Cx->I2SR &= ~(1<<1);
    i2c_master_stop(I2Cx);
}

void i2c_master_read(I2C_Type * I2Cx , unsigned char * buf , unsigned int size){
    
    volatile unsigned char dummy = 0;
    dummy++;

    /*清除中断标志位*/
    I2Cx->I2SR &= ~(1<<1);

    /*设置发送模式*/
    I2Cx->I2CR &= ~( (1<<4) | (1<<3) );

    if(size == 1)
        I2Cx->I2CR |= 1<<3;

    dummy = I2Cx->I2DR;     /*假读*/
    
    while(size--){
        while ( !( I2Cx->I2SR & ( 1<<1 ) ) );/*等待发送完成*/
        I2Cx->I2SR &= ~(1<<1);

        if(size == 0){  /*数据发送完成要发送stop信号*/
            i2c_master_stop(I2Cx);
        }

        if(size == 1){  /*倒数第一个数据时，要设置NACK信号*/
            I2Cx->I2CR |= 1<<3;
        }
        *buf++ = I2Cx->I2DR;
    }
}

unsigned char i2c_master_transfer(I2C_Type *base, struct i2c_transfer *xfer)
{
	unsigned char ret = 0;
	 enum i2c_direction direction = xfer->direction;	

	base->I2SR &= ~((1 << 1) | (1 << 4));			/* 清除标志位 */

	/* 等待传输完成 */
	while(!((base->I2SR >> 7) & 0X1)){}; 

	/* 如果是读的话，要先发送寄存器地址，所以要先将方向改为写 */
    if ((xfer->subaddressSize > 0) && (xfer->direction == read))
    {
        direction = write;
    }

	ret = i2c_master_start(base, xfer->slaveAddress, direction); /* 发送开始信号 */
    if(ret)
    {	
		return ret;
	}

	while(!(base->I2SR & (1 << 1))){};			/* 等待传输完成 */

    ret = i2c_check_and_clear_error(base, base->I2SR);	/* 检查是否出现传输错误 */
    if(ret)
    {
      	i2c_master_stop(base); 						/* 发送出错，发送停止信号 */
        return ret;
    }
	
    /* 发送寄存器地址 */
    if(xfer->subaddressSize)
    {
        do
        {
			base->I2SR &= ~(1 << 1);			/* 清除标志位 */
            xfer->subaddressSize--;				/* 地址长度减一 */
			
            base->I2DR =  ((xfer->subaddress) >> (8 * xfer->subaddressSize)); //向I2DR寄存器写入子地址
  
			while(!(base->I2SR & (1 << 1)));  	/* 等待传输完成 */

            /* 检查是否有错误发生 */
            ret = i2c_check_and_clear_error(base, base->I2SR);
            if(ret)
            {
             	i2c_master_stop(base); 				/* 发送停止信号 */
             	return ret;
            }  
        } while ((xfer->subaddressSize > 0) && (ret == I2C_STATUS_OK));

        if(xfer->direction == read) 		/* 读取数据 */
        {
            base->I2SR &= ~(1 << 1);			/* 清除中断挂起位 */
            i2c_master_repeated_start(base, xfer->slaveAddress, read); /* 发送重复开始信号和从机地址 */
    		while(!(base->I2SR & (1 << 1))){};/* 等待传输完成 */
            /* 检查是否有错误发生 */
			ret = i2c_check_and_clear_error(base, base->I2SR);
            if(ret)
            {
             	ret = I2C_STATUS_ADDRNAK;
                i2c_master_stop(base); 		/* 发送停止信号 */
                return ret;  
            }
           	          
        }
    }	


    /* 发送数据 */
    if ((xfer->direction == write) && (xfer->dataSize > 0))
    {
    	i2c_master_write(base, xfer->data, xfer->dataSize);
	}

    /* 读取数据 */
    if ((xfer->direction == read) && (xfer->dataSize > 0))
    {
       	i2c_master_read(base, xfer->data, xfer->dataSize);
	}
	return 0;	
}